/*
 * Equip.cpp
 *
 *  Created on: 2013. 9. 11.
 *      Author: jjaehuny
 */

#include "Equip.h"
#include "Item.h"
#include "Bag.h"
#include "Static.h"
#include "../User.h"
#include "../Proxy.h"

#include "../NResource/Static.h"

namespace ProjectZ { namespace NLogic {

Equip::Equip(User * pUser) : _user(pUser)
{
	_clsEquipTree.clear();
}

Equip::~Equip() {
}

void
Equip::Initialize()
{
	_clsEquipTree.clear();
}

void
Equip::Finalize()
{
	// MEMO: 장비는 Bag 에서 삭제하므로 여기서 삭제할 필요가 없다
	//NLogic::Static::InstancePtr()->DEL_ITEM( _clsEquipVector[i] );
	_clsEquipTree.clear();
}

bool
Equip::AddItem(EnumItemEquipPosition ePosition, Item * pItem)
{
	if (EnumItemEquipPosition::ITEM_EQUIP_POS_NONE >= ePosition)
	{
//		DEBUGLOG("%s()> FAILED> itemseq: %d> 10. ePos: %d", __FUNCTION__, pItem->GetItemSeq(), ePosition);
		return false;
	}
	if (EnumItemEquipPosition::MAX_ITEM_EQUIP_POS <= ePosition && EnumItemEquipPosition::ITEM_EQUIP_POS_NAME_TAG < ePosition)
	{
//		DEBUGLOG("%s()> FAILED>  itemseq: %d> 20. ePos: %d", __FUNCTION__, pItem->GetItemSeq(), ePosition);
		return false;
	}

	int itemType = NResource::Static::Instance().GetItemResource()->GetItemSubType(pItem->GetData());


	if (ePosition != ITEM_EQUIP_POS_NAME_TAG && static_cast<int>(ePosition) != itemType)
	{
//		DEBUGLOG("%s()> FAILED>  itemseq: %d> 30. ePos: %d, itemType: %d(sub_type:%d, tid:%d, class_type:%d)"
//				, __FUNCTION__, pItem->GetItemSeq(), ePosition, itemType, pItem->GetData().sub_type, pItem->GetData().tid, pItem->GetData().class_type);
		return false;
	}

	if (ePosition == ITEM_EQUIP_POS_NAME_TAG && itemType != 62 && itemType != 63)
	{
//		DEBUGLOG("%s()> FAILED>  itemseq: %d> 40. ePos: %d, itemType: %d(sub_type:%d, tid:%d, class_type:%d)"
//				, __FUNCTION__, pItem->GetItemSeq(), ePosition, itemType, pItem->GetData().sub_type, pItem->GetData().tid, pItem->GetData().class_type);
		return false;
	}

	auto iter = _clsEquipTree.find(ePosition);
	if (_clsEquipTree.end() != iter)
	{
		Item * pOldItem = iter->second;
		pOldItem->SetEquip(EnumItemEquipPosition::ITEM_EQUIP_POS_NONE);
	}

	_clsEquipTree[static_cast<int>(ePosition)] = pItem;
	pItem->SetEquip(ePosition);

	return true ;
}

Item *
Equip::GetItem(EnumItemEquipPosition ePosition)
{
	auto iter = _clsEquipTree.find(ePosition);
	if (_clsEquipTree.end() == iter)
		return NULL;

	if (ITEM_EQUIP_POS_NAME_TAG == ePosition)
	{
		if (time(NULL) > iter->second->GetData().reg_date + (iter->second->GetData().eff_value[0] * 60))
		{
			this->PopItem(ITEM_EQUIP_POS_NAME_TAG);
			this->UpdateCharacterInfo();
			return NULL;
		}
	}

	return iter->second;
}

Item *
Equip::PopItem(EnumItemEquipPosition ePosition)
{
	auto iter = _clsEquipTree.find(ePosition);
	if (_clsEquipTree.end() == iter)
		return NULL;

//	if (0 == _user->GetSocialID().compare("88812375964287473") && ITEM_EQUIP_POS_NAME_TAG == ePosition)
//		::Logger::GETLOG()->ToAll(::Logger::OBSERVER, "[ITEM_EQUIP_POS_NAME_TAG POP] curtime[%d] sumtime[%d] (regtime[%d] + effvalue[%d] * 60)",
//				time(NULL) , iter->second->GetData().reg_date + (iter->second->GetData().eff_value[0] * 60),
//				iter->second->GetData().reg_date, iter->second->GetData().eff_value[0] );

	Item * pItem = iter->second;
	pItem->SetEquip(EnumItemEquipPosition::ITEM_EQUIP_POS_NONE);
	_clsEquipTree.erase(ePosition);

	return pItem;
}

bool
Equip::IsExistItem(EnumItemEquipPosition ePosition)
{
	if (NULL != this->GetItem(ePosition))
		return true;

//	auto iter = _clsEquipTree.find(ePosition);
//	if (_clsEquipTree.end() != iter)
//		return true;

	return false;
}

Equip::EQUIPTREE &
Equip::GetEquipTree()
{
	return _clsEquipTree;
}

// equip 정보를 돌면서 characterinfo 에 업데이트 한다.
void
Equip::UpdateCharacterInfo()
{
	if (false == _user->IsCacheBagInfo())
		return;

	// 이런 경우 업데이트 불가 처리....
	if (false == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_WEAPON) ||
		false == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_FAIRY) ||
		false == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_VEHICLE))
	{
		return;
	}

	if (true == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_WEAPON))
	{
		_user->GetCharacterInfo().weapon = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_WEAPON)->GetItemSeq();
		_user->GetCharacterInfo().weapon_iconidx = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_WEAPON)->GetData().iconidx;
	}
	else
	{
		_user->GetCharacterInfo().weapon = 0;
		_user->GetCharacterInfo().weapon_iconidx = 0;
	}

	if (true == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_HELMET))
	{
		_user->GetCharacterInfo().helmet = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_HELMET)->GetItemSeq();
		_user->GetCharacterInfo().helmet_iconidx = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_HELMET)->GetData().iconidx;
	}
	else
	{
		_user->GetCharacterInfo().helmet = 0;
		_user->GetCharacterInfo().helmet_iconidx = 0;
	}

	if (true == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_ARMOR))
	{
		_user->GetCharacterInfo().armor = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_ARMOR)->GetItemSeq();
		_user->GetCharacterInfo().armor_iconidx = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_ARMOR)->GetData().iconidx;
	}
	else
	{
		_user->GetCharacterInfo().armor = 0;
		_user->GetCharacterInfo().armor_iconidx = 0;
	}

	if (true == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_GLOVE))
	{
		_user->GetCharacterInfo().glove = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_GLOVE)->GetItemSeq();
	}
	else
	{
		_user->GetCharacterInfo().glove = 0;
	}

	if (true == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_SHOES))
	{
		_user->GetCharacterInfo().shoes = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_SHOES)->GetItemSeq();
	}
	else
	{
		_user->GetCharacterInfo().shoes = 0;
	}

	if (true == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_NECKLACE))
	{
		_user->GetCharacterInfo().necklace = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_NECKLACE)->GetItemSeq();
	}
	else
	{
		_user->GetCharacterInfo().necklace = 0;
	}

	if (true == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_CLOAK))
	{
		_user->GetCharacterInfo().cloak = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_CLOAK)->GetItemSeq();
	}
	else
	{
		_user->GetCharacterInfo().cloak = 0;
	}

	if (true == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_RING))
	{
		_user->GetCharacterInfo().ring = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_RING)->GetItemSeq();
	}
	else
	{
		_user->GetCharacterInfo().ring = 0;
	}

	if (true == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_CHARM))
	{
		_user->GetCharacterInfo().charm = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_CHARM)->GetItemSeq();
	}
	else
	{
		_user->GetCharacterInfo().charm = 0;
	}

	if (true == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_AVARTAR))
	{
		_user->GetCharacterInfo().avartar = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_AVARTAR)->GetItemSeq();
		_user->GetCharacterInfo().avartar_iconidx = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_AVARTAR)->GetData().iconidx;
	}
	else
	{
		_user->GetCharacterInfo().avartar = 0;
		// 아바타가 없는 경우 기본을 1000 으로 변경한다... 예외를 위해서..
		_user->GetCharacterInfo().avartar_iconidx = 1000;
	}

	if (true == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_VEHICLE))
	{
		_user->GetCharacterInfo().vehicle = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_VEHICLE)->GetItemSeq();
		_user->GetCharacterInfo().vehicle_iconidx = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_VEHICLE)->GetData().iconidx;
	}
	else
	{
		_user->GetCharacterInfo().vehicle = 0;
		_user->GetCharacterInfo().vehicle_iconidx = 0;
	}

	if (true == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_TITLE))
	{
		_user->GetCharacterInfo().title = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_TITLE)->GetItemSeq();
	}
	else
	{
		_user->GetCharacterInfo().title = 0;
	}

	if (true == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_FAIRY))
	{
		_user->GetCharacterInfo().fairy = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_FAIRY)->GetItemSeq();
	}
	else
	{
		_user->GetCharacterInfo().fairy = 0;
	}

	if (true == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_PET))
	{
		_user->GetCharacterInfo().battlepet = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_PET)->GetItemSeq();
	}
	else
	{
		_user->GetCharacterInfo().battlepet = 0;
	}

	if (true == this->IsExistItem(EnumItemEquipPosition::ITEM_EQUIP_POS_NAME_TAG))
	{
		_user->GetCharacterInfo().name_tag = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_NAME_TAG)->GetItemSeq();
		_user->GetCharacterInfo().name_tag_iconidx = this->GetItem(EnumItemEquipPosition::ITEM_EQUIP_POS_NAME_TAG)->GetData().iconidx;
	}
	else
	{
		_user->GetCharacterInfo().name_tag = 0;
		_user->GetCharacterInfo().name_tag_iconidx = 0;
	}
	NProxy::SetMainCharacterInfo(_user);
}

void
Equip::EquipAddFromCharacterInfo( int a_iCaller )
{
	// Added by spencer(2014.07.04)
	// 무기/탈것/페어리 벗겨지는 오류에 대한 로그 추가
	if ( 0 < a_iCaller && (0 == _user->GetCharacterInfo().weapon || 0 == _user->GetCharacterInfo().vehicle || 0 == _user->GetCharacterInfo().fairy))
	{
		DEBUGLOG("%s()> FAILED>  userseq: %d, charseq: %d> 10. weapon: %d, vehicle: %d, fairy: %d> caller: %d, state: %s"
		    , __FUNCTION__, _user->GetUserSeq(), _user->GetCharacterInfo().characterseq, _user->GetCharacterInfo().weapon, _user->GetCharacterInfo().vehicle, _user->GetCharacterInfo().fairy
		    , a_iCaller, _user->GetState()->GetName().c_str()
		    );
	}
	
	if (0 != _user->GetCharacterInfo().weapon)
	{
		Item * pItem = _user->GetBag(BAG_TYPE_NORMAL)->GetItem(_user->GetCharacterInfo().weapon);
		if (NULL != pItem)
		{
			AddItem(EnumItemEquipPosition::ITEM_EQUIP_POS_WEAPON, pItem);
		}
		else if ( 0 < a_iCaller )
		{
			// Added by spencer(2014.07.04)
			// 무기/탈것/페어리 벗겨지는 오류에 대한 로그 추가
			int irgLoaded[(int)BAG_TYPE_MAX] = { 0,0,0, };
			int irgCount[(int)BAG_TYPE_MAX] = { 0,0,0, };
			for(int i = static_cast<int>(BAG_TYPE_NORMAL); i < static_cast<int>(BAG_TYPE_MAX); ++i)
			{
				NLogic::Bag * pBag = _user->GetBag(static_cast<INVEN_BAG_TYPE>(i));
				if (NULL != pBag && pBag->IsLoad())
				{
					irgLoaded[i] = 1;
					irgCount[i] = pBag->HasItemCount();
				}
			}

			DEBUGLOG("%s()> FAILED>  userseq: %d, charseq: %d> 20. pItem is NULL> weapon: %d> caller: %d, state: %s, Bag0(%d,%d), Bag1(%d,%d), Bag2(%d,%d), Bag3(%d,%d), Bag4(%d,%d), Bag5(%d,%d)"
				, __FUNCTION__, _user->GetUserSeq(), _user->GetCharacterInfo().characterseq, _user->GetCharacterInfo().weapon
				, a_iCaller , _user->GetState()->GetName().c_str()
				, irgLoaded[0], irgCount[0], irgLoaded[1], irgCount[1], irgLoaded[2], irgCount[2], irgLoaded[3], irgCount[3], irgLoaded[4], irgCount[4], irgLoaded[5], irgCount[5]);
		}
	}

	if (0 != _user->GetCharacterInfo().helmet)
	{
		Item * pItem = _user->GetBag(BAG_TYPE_NORMAL)->GetItem(_user->GetCharacterInfo().helmet);
		if (NULL != pItem)
		{
			AddItem(EnumItemEquipPosition::ITEM_EQUIP_POS_HELMET, pItem);
		}
	}

	if (0 != _user->GetCharacterInfo().armor)
	{
		Item * pItem = _user->GetBag(BAG_TYPE_NORMAL)->GetItem(_user->GetCharacterInfo().armor);
		if (NULL != pItem)
		{
			AddItem(EnumItemEquipPosition::ITEM_EQUIP_POS_ARMOR, pItem);
		}
	}

	if (0 != _user->GetCharacterInfo().glove)
	{
		Item * pItem = _user->GetBag(BAG_TYPE_NORMAL)->GetItem(_user->GetCharacterInfo().glove);
		if (NULL != pItem)
		{
			AddItem(EnumItemEquipPosition::ITEM_EQUIP_POS_GLOVE, pItem);
		}
	}

	if (0 != _user->GetCharacterInfo().shoes)
	{
		Item * pItem = _user->GetBag(BAG_TYPE_NORMAL)->GetItem(_user->GetCharacterInfo().shoes);
		if (NULL != pItem)
		{
			AddItem(EnumItemEquipPosition::ITEM_EQUIP_POS_SHOES, pItem);
		}
	}

	if (0 != _user->GetCharacterInfo().necklace)
	{
		Item * pItem = _user->GetBag(BAG_TYPE_ACCESSORY)->GetItem(_user->GetCharacterInfo().necklace);
		if (NULL != pItem)
		{
			AddItem(EnumItemEquipPosition::ITEM_EQUIP_POS_NECKLACE, pItem);
		}
	}

	if (0 != _user->GetCharacterInfo().cloak)
	{
		Item * pItem = _user->GetBag(BAG_TYPE_ACCESSORY)->GetItem(_user->GetCharacterInfo().cloak);
		if (NULL != pItem)
		{
			AddItem(EnumItemEquipPosition::ITEM_EQUIP_POS_CLOAK, pItem);
		}
	}

	if (0 != _user->GetCharacterInfo().ring)
	{
		Item * pItem = _user->GetBag(BAG_TYPE_ACCESSORY)->GetItem(_user->GetCharacterInfo().ring);
		if (NULL != pItem)
		{
			AddItem(EnumItemEquipPosition::ITEM_EQUIP_POS_RING, pItem);
		}
	}

	if (0 != _user->GetCharacterInfo().charm)
	{
		Item * pItem = _user->GetBag(BAG_TYPE_ACCESSORY)->GetItem(_user->GetCharacterInfo().charm);
		if (NULL != pItem)
		{
			AddItem(EnumItemEquipPosition::ITEM_EQUIP_POS_CHARM, pItem);
		}
	}

	if (0 != _user->GetCharacterInfo().avartar)
	{
		Item * pItem = _user->GetBag(BAG_TYPE_NORMAL)->GetItem(_user->GetCharacterInfo().avartar);
		if (NULL != pItem)
		{
			AddItem(EnumItemEquipPosition::ITEM_EQUIP_POS_AVARTAR, pItem);
		}
	}

	if (0 != _user->GetCharacterInfo().vehicle)
	{
		Item * pItem = _user->GetBag(BAG_TYPE_MISC)->GetItem(_user->GetCharacterInfo().vehicle);
		if (NULL != pItem)
		{
			AddItem(EnumItemEquipPosition::ITEM_EQUIP_POS_VEHICLE, pItem);
		}
		else if ( 0 < a_iCaller )
		{
			// Added by spencer(2014.07.04)
			// 무기/탈것/페어리 벗겨지는 오류에 대한 로그 추가
			DEBUGLOG("%s()> FAILED>  userseq: %d, charseq: %d> 30. pItem is NULL> vehicle: %d> caller: %d"
			    , __FUNCTION__, _user->GetUserSeq(), _user->GetCharacterInfo().characterseq, _user->GetCharacterInfo().vehicle, a_iCaller);
		}		
	}

	if (0 != _user->GetCharacterInfo().title)
	{
		Item * pItem = _user->GetBag(BAG_TYPE_TITLE)->GetItem(_user->GetCharacterInfo().title);
		if (NULL != pItem)
		{
			AddItem(EnumItemEquipPosition::ITEM_EQUIP_POS_TITLE, pItem);
		}
	}

	if (0 != _user->GetCharacterInfo().fairy)
	{
		Item * pItem = _user->GetBag(BAG_TYPE_FAIRY)->GetItem(_user->GetCharacterInfo().fairy);
		if (NULL != pItem)
		{
			AddItem(EnumItemEquipPosition::ITEM_EQUIP_POS_FAIRY, pItem);
		}
		else if ( 0 < a_iCaller )
		{
			// Added by spencer(2014.07.04)
			// 무기/탈것/페어리 벗겨지는 오류에 대한 로그 추가
			DEBUGLOG("%s()> FAILED>  userseq: %d, charseq: %d> 40. pItem is NULL> fairy: %d> caller: %d"
			    , __FUNCTION__, _user->GetUserSeq(), _user->GetCharacterInfo().characterseq, _user->GetCharacterInfo().fairy, a_iCaller );
		}		
	}

	if (0 != _user->GetCharacterInfo().battlepet)
	{
		Item * pItem = _user->GetBag(BAG_TYPE_BATTLE_PET)->GetItem(_user->GetCharacterInfo().battlepet);
		if (NULL != pItem)
		{
			AddItem(EnumItemEquipPosition::ITEM_EQUIP_POS_PET, pItem);
		}
	}

	if (0 != _user->GetCharacterInfo().name_tag)
	{
		Item * pItem = _user->GetBag(BAG_TYPE_MISC)->GetItem(_user->GetCharacterInfo().name_tag);
		if (NULL != pItem)
		{
			AddItem(EnumItemEquipPosition::ITEM_EQUIP_POS_NAME_TAG, pItem);
		}
	}
}

int
Equip::HasItemCount()
{
	auto iter = _clsEquipTree.find(ITEM_EQUIP_POS_NAME_TAG);
	if (_clsEquipTree.end() != iter)
	{
		if (time(NULL) > iter->second->GetData().reg_date + (iter->second->GetData().eff_value[0] * 60))
		{
			this->PopItem(ITEM_EQUIP_POS_NAME_TAG);
			this->UpdateCharacterInfo();
		}
	}

	return static_cast<int>(_clsEquipTree.size());
}

int
Equip::GetEquipItemIconIndex(EnumItemEquipPosition ePosition)
{
	int iconIndex = 0;

	if (true == this->IsExistItem(ePosition))
		iconIndex = this->GetItem(ePosition)->GetData().iconidx;

	return iconIndex;
}

} /*NLogic*/ } /* namespace ProjectZ */
